﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    /// <summary>
    ///  计算指定日期是星期几
    /// </summary>
    public class CalcWeekDay
    {
        #region 成员
        /// <summary>
        /// 年份
        /// </summary>
        public int Year { get; set; }
        /// <summary>
        /// 月份
        /// </summary>
        public int Month { get; set; }
        /// <summary>
        /// 天数
        /// </summary>
        public int Day { get; set; }
        /// <summary>
        /// 总天数
        /// </summary>
        public int totalDay { get; private set; }

        public CalcWeekDay()
        {
            Year = 1990;
            Month = 1;
            Day = 1;
            totalDay = 0;
        }
        #endregion

        #region 方法

        /// <summary>
        /// 判断指定年份是否为闰年
        /// </summary>
        /// <param name="year">指定年份</param>
        /// <returns>返回true表示指定年份是闰年</returns>
        private bool IsLoopYear(int year)
        {
            return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0) ? true : false;
            //return DateTime.IsLeapYear(year);//效过等同
        }

        /// <summary>
        /// 计算从1900年到指定年份的总天数
        /// </summary>
        /// <param name="desYear">指定年份</param>
        /// <returns>返回年份段的总天数</returns>
        private int GetTotalDayByYear(int desYear)
        {
            int temp = 0;
            for (int i = 1900; i < desYear; i++)
            {
                temp = IsLoopYear(i) == true ? temp + 366 : temp + 365;
            }
            return temp;
        }

        /// <summary>
        /// 计算指定的年份从1月到指定月份的总天数
        /// </summary>
        /// <param name="desYear">指定年份</param>
        /// <param name="desMonth">指定月份</param>
        /// <returns>返回指定年份从一月到指定月份的总天数</returns>
        private int GetTotalDayByMonth(int desYear, int desMonth)
        {
            int temp = 0;
            for (int m = 1; m < desMonth; m++)
            {
                if (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12)
                {
                    temp += 31;
                }
                else if (m == 4 || m == 6 || m == 9 || m == 11)
                {
                    temp += 30;
                }
                else
                {
                    if (IsLoopYear(desYear))
                    {
                        temp += 29;
                    }
                    else
                    {
                        temp += 28;
                    }
                }
            }
            return temp;
        }

        /// <summary>
        /// 打印指定日期是星期几
        /// </summary>
        public void PrintWeekDayByDate()
        {
            //计算三部分总天数
            totalDay = GetTotalDayByYear(Year) + GetTotalDayByMonth(Year, Month) + Day;
            //打印日期、星期几
            Console.Write("从1990-1-1到{0}-{1}-{2}总共{3}天！     ", Year, Month, Day, totalDay);
            Console.Write("{0}年{1}月{2}日是", Year, Month, Day);
            switch (totalDay % 7)
            {
                case 0: Console.WriteLine("星期日"); break;
                case 1: Console.WriteLine("星期一"); break;
                case 2: Console.WriteLine("星期二"); break;
                case 3: Console.WriteLine("星期三"); break;
                case 4: Console.WriteLine("星期四"); break;
                case 5: Console.WriteLine("星期五"); break;
                case 6: Console.WriteLine("星期六"); break;
                default:
                    break;
            }
        }

        /// <summary>
        /// 打印日历头部
        /// </summary>
        public void PrintWeekDay()
        {
            Console.Write("日\t一\t二\t三\t四\t五\t六");

            #region 计算指定日期是星期几
            int temp = 0;
            switch (totalDay % 7)
            {
                case 0: temp = 0; break;
                case 1: temp = 1; break;
                case 2: temp = 2; break;
                case 3: temp = 3; break;
                case 4: temp = 4; break;
                case 5: temp = 5; break;
                case 6: temp = 6; break;
                default:
                    break;
            }
            #endregion

            #region 打印每月1号前面的空格
            for (int i = 0; i < temp; i++)
            {
                Console.Write("\t");
            }
            for (int i = 1; i <= 7 - temp; i++)
            {
                if (i == 7 - temp)
                {
                    Console.Write(i);
                }
                Console.Write(i + "\t");
            }
            #endregion

            #region 打印每月的日期
            Console.WriteLine();
            int numTemp = 0;
            for (int i = temp; i <= GetNumDays(Year, Month); i++)
            {
                Console.Write(i + "\t");
                numTemp++;
                if (numTemp % 7 == 6)
                {
                    Console.WriteLine();
                }
            }
            //for (int i = 1; i <= 30; i++)
            //{
            //    Console.Write(i + "\t");
            //    if ((temp + i) % 7 == 6)
            //    {
            //        Console.WriteLine();
            //    }
            //}
            #endregion
        }

        /// <summary>
        /// 指定年份、指定月份，判断这个月有多少天
        /// </summary>
        /// <param name="desYear">指定年份</param>
        /// <param name="desMonth">指定月份</param>
        /// <returns>返回该月的天数</returns>
        private int GetNumDays(int desYear, int desMonth)
        {
            int temp = 0;
            if (IsLoopYear(desYear) && desMonth == 2)
            {
                temp = 29;
            }
            else if (desMonth == 2)
            {
                temp = 28;
            }
            else
            {
                temp = (Month == 1 || Month == 3 || Month == 5 || Month == 7 || Month == 8 || Month == 10 || Month == 12) ? 31 : 30;
            }
            return temp;
        }
        #endregion
    }
}
